#include "vectorfont.h"
#include <QFile>
#include <qmath.h>
#include "main.h"

VectorFont::VectorFont(QObject *parent) :
    QObject(parent)
{
    m_iDPMM = 40;
    m_pChinese_char = NULL;
    m_pEnglish_char = NULL;
    m_nChinese_char_count = 0;
    m_nEnglish_char_count = 0;
    IniVectorFont();
}

VectorFont::~VectorFont()
{
    if(m_pChinese_char != NULL)
    {
        delete []m_pChinese_char;
        m_pChinese_char = NULL;
    }
    if(m_pEnglish_char != NULL)
    {
        delete []m_pEnglish_char;
        m_pEnglish_char = NULL;
    }
}

void VectorFont::IniVectorFont()
{
    QFile fntFile;
    QString strCharFileName;

    BYTE byte[10];
    int nCharCount_C;
    int nCharCount_E;
    CChinese_char Chinese_char1;
    CEnglish_char English_char1;
    int nCountChar;


    QString appPath = QCoreApplication::applicationDirPath();
    QChar separator = QChar('/');
    if(!appPath.contains(separator))    // 判断分隔符
    {
        separator = QChar('\\');
    }
    m_workPath = appPath + separator;


    strCharFileName = m_workPath + "english.fnt";
    //qDebug()<< "strCharFileName" << strCharFileName;
    fntFile.setFileName(strCharFileName);

    if(!fntFile.open(QIODevice::ReadOnly))
    {
        qDebug() <<"english file open failed";
        return;
    }

    fntFile.seek(0);
    fntFile.read((char*)byte,10);

    m_nInternalLeading_E=(int)((WORD)byte[0] | ((WORD)byte[1] << 8));
    m_nHeight_E=(int)((WORD)byte[2] | ((WORD)byte[3] << 8));
    m_nDescent_E=(int)((WORD)byte[4] | ((WORD)byte[5] << 8));
    nCharCount_E=(int)((DWORD)byte[6] | ((DWORD)byte[7] << 8) | ((DWORD)byte[9] << 16) | ((DWORD)byte[9] << 24));
    //m_aEnglish_char.clear();
    m_pEnglish_char = new CEnglish_char[nCharCount_E];
    m_nEnglish_char_count = nCharCount_E;
    fntFile.seek(10);

    nCountChar=nCharCount_E;
    while (nCountChar > 0)
    {
        fntFile.read((char*)byte,10);

        English_char1.m_wCharCode=(WORD)byte[0] | ((WORD)byte[1] << 8);
        English_char1.m_wBytes=(WORD)byte[2] | ((WORD)byte[3] << 8);
        English_char1.m_wWidth=(WORD)byte[4] | ((WORD)byte[5] << 8);
        English_char1.m_dwPosition=(DWORD)byte[6] | ((DWORD)byte[7] << 8) | ((DWORD)byte[9] << 16) | ((DWORD)byte[9] << 24);

        m_pEnglish_char[nCharCount_E-nCountChar] = English_char1;
        //m_aEnglish_char.append(English_char1);

        nCountChar--;
    }
    fntFile.close();

    strCharFileName = m_workPath + "Hz.fnt";
    //qDebug()<< "strCharFileName" << strCharFileName;
    fntFile.setFileName(strCharFileName);
    if(!fntFile.open(QIODevice::ReadOnly))
    {
        qDebug() <<"chinese file open failed";
        return;
    }
    fntFile.seek(0);
    fntFile.read((char*)byte,8);

    m_nWidth_C=(int)((WORD)byte[0] | ((WORD)byte[1] << 8));
    m_nHeight_C=(int)((WORD)byte[2] | ((WORD)byte[3] << 8));
    nCharCount_C=(int)((DWORD)byte[4] | ((DWORD)byte[5] << 8) | ((DWORD)byte[6] << 16) | ((DWORD)byte[7] << 24));

    //m_aChinese_char.clear();
    m_pChinese_char = new CChinese_char[nCharCount_C];
    m_nChinese_char_count = nCharCount_C;

    fntFile.seek(8);
    nCountChar=nCharCount_C;
    while (nCountChar > 0)
    {
        fntFile.read((char*)byte,8);

        Chinese_char1.m_wCharCode=(WORD)byte[0] | ((WORD)byte[1] << 8);
        Chinese_char1.m_wBytes=(WORD)byte[2] | ((WORD)byte[3] << 8);
        Chinese_char1.m_dwPosition=(DWORD)byte[4] | ((DWORD)byte[5] << 8) | ((DWORD)byte[6] << 16) | ((DWORD)byte[7] << 24);


        m_pChinese_char[nCharCount_C-nCountChar] = Chinese_char1;
        //m_aChinese_char.append(Chinese_char1);
        nCountChar--;
    }
    fntFile.close();

    m_dFontAngle = 0;
    m_dFontHeight = 0.375 * 10 * m_iDPMM;
}


//输入参数:
//  ptPointLU  显示字符串的左上角坐标(即TextOut(...)的x,y值)
//  pbyData 字符的描述数据
//  wBytes 字符的描述数据个数
//  nLeft,nDown 字符的左下角坐标(即以英汉字库的公共单位及坐标水平绘制字符串时,字符的的左下角坐标)
//  nFontScale 字库的长度比例
void VectorFont::PlotChar(QPoint ptPointLU,BYTE *pbyData,WORD wBytes,int nLeft,int nDown,int nFontScale)
{
    BYTE byByteX,byByteY;
    QPoint ptCurrentPos,ptCenter,ptPointS,ptPointE;
    QPoint ptPoint1;
    WORD wIndex1;
    WORD wDirection,wLength;
    BOOL bPenUp,bVerTextCommand,bClockwise;
    WORD wRadius,wArcS,wSpan;
    int nRadius;
    double dAngleS,dAngleE,dAngleOffsetS,dAngleOffsetE;
    double dx1,dy1,dx2,dy2,dxc,dyc,dr,dD,dH,dBulge;
    double dCos,dSin;
    double dLToDScale;
    int nHeight;

    if (wBytes == 0)  return;

    nHeight=(m_nInternalLeading_E + m_nHeight_E) * m_nHeight_E;
    //nHeight=(m_nInternalLeading_E + m_nHeight_E) * m_nHeight_C; //之前
    dLToDScale=(double)nHeight / m_dFontHeight;

    m_dRake = m_dFontAngle/180.0*PI;
    dCos=cos(m_dRake);
    dSin=sin(m_dRake);

    ptCurrentPos=QPoint(nLeft,nDown);
    ptPoint1=CPToLP(ptCurrentPos,nHeight,ptPointLU,dSin,dCos,dLToDScale);
    MoveTo(ptPoint1);
    bVerTextCommand=false;
    bPenUp=false;
    wIndex1=0;
    while (wIndex1 < wBytes)  {
        switch (pbyData[wIndex1])  {
        case 0x0:
            wIndex1++;
            break;
        case 0x1:
            wIndex1++;
            bPenUp=false;
            break;
        case 0x2:
            wIndex1++;
            bPenUp=true;
            break;
        case 0x3:
            wIndex1++;
            wIndex1++;
            bVerTextCommand=false;
            break;
        case 0x4:
            wIndex1++;
            wIndex1++;
            bVerTextCommand=false;
            break;
        case 0x5:
            wIndex1++;
            bPenUp=true;
            break;
        case 0x6:
            wIndex1++;
            bPenUp=true;
            break;
        case 0x7:
            wIndex1++;
            wIndex1++;
            bPenUp=true;
            break;
        case 0x8:
            if (bVerTextCommand)  {
                wIndex1=wIndex1+3;
            }
            else  {
                wIndex1++;
                ptCurrentPos.setX(ptCurrentPos.x() + (char)pbyData[wIndex1] * nFontScale);
                wIndex1++;
                ptCurrentPos.setY(ptCurrentPos.y() + (char)pbyData[wIndex1] * nFontScale);

                ptPoint1=CPToLP(ptCurrentPos,nHeight,ptPointLU,dSin,dCos,dLToDScale);
                if (bPenUp)
                    MoveTo(ptPoint1);
                else
                    LineTo(ptPoint1);

                wIndex1++;
            }
            bVerTextCommand=false;
            break;
        case 0x9:
            if (bVerTextCommand)  {
                wIndex1++;
                byByteX=pbyData[wIndex1];
                wIndex1++;
                byByteY=pbyData[wIndex1];
                while ((byByteX != 0) || (byByteY != 0))  {
                    wIndex1++;
                    byByteX=pbyData[wIndex1];
                    wIndex1++;
                    byByteY=pbyData[wIndex1];
                }
                wIndex1++;
            }
            else  {
                wIndex1++;
                byByteX=pbyData[wIndex1];
                wIndex1++;
                byByteY=pbyData[wIndex1];
                while ((byByteX != 0) || (byByteY != 0))  {
                    ptCurrentPos.setX(ptCurrentPos.x() + (char)byByteX * nFontScale);
                    ptCurrentPos.setY(ptCurrentPos.y() + (char)byByteY * nFontScale);

                    ptPoint1=CPToLP(ptCurrentPos,nHeight,ptPointLU,dSin,dCos,dLToDScale);
                    if (bPenUp)
                        MoveTo(ptPoint1);
                    else
                        LineTo(ptPoint1);

                    wIndex1++;
                    byByteX=pbyData[wIndex1];
                    wIndex1++;
                    byByteY=pbyData[wIndex1];
                }

                wIndex1++;
            }
            bVerTextCommand=false;
            break;
        case 0xA:
            if (bVerTextCommand)  {
                wIndex1=wIndex1+3;
            }
            else  {
                wIndex1++;
                wRadius=(WORD)pbyData[wIndex1];
                wIndex1++;
                /*if (((char)pbyData[wIndex1]) < 0)  bClockwise=true;
                else*/  bClockwise=false;
                wArcS=(WORD)pbyData[wIndex1];
                wArcS=wArcS & 0x70;
                wArcS=wArcS >> 4;
                wSpan=(WORD)pbyData[wIndex1];
                wSpan=wSpan & 0x7;

                //计算圆心
                ptCenter=ptCurrentPos;
                ptCenter.setX(ptCenter.x() - ((double)wRadius * (double)nFontScale * cos((double)wArcS * 45.0 / 180.0 * 3.14159265359))+0.5);
                ptCenter.setY(ptCenter.y() - ((double)wRadius * (double)nFontScale * sin((double)wArcS * 45.0 / 180.0 * 3.14159265359))+0.5);

                dAngleS=(double)wArcS * 45.0 / 180.0 * 3.14159265359;
                if (bClockwise)  dAngleE=dAngleS - (double)wSpan * 45.0 / 180.0 * 3.14159265359;
                else  dAngleE=dAngleS + (double)wSpan * 45.0 / 180.0 * 3.14159265359;

                if (bClockwise)  {
                    ptPointS.setX(ptCenter.x() + (double)wRadius * (double)nFontScale * cos(dAngleE)+0.5);
                    ptPointS.setY(ptCenter.y() + (double)wRadius * (double)nFontScale * sin(dAngleE)+0.5);
                    ptPointE.setX(ptCenter.x() + (double)wRadius * (double)nFontScale * cos(dAngleS)+0.5);
                    ptPointE.setY(ptCenter.y() + (double)wRadius * (double)nFontScale * sin(dAngleS)+0.5);
                    ptCurrentPos=ptPointS;
                }
                else  {
                    ptPointS.setX(ptCenter.x() + (double)wRadius * (double)nFontScale * cos(dAngleS)+0.5);
                    ptPointS.setY(ptCenter.y() + (double)wRadius * (double)nFontScale * sin(dAngleS)+0.5);
                    ptPointE.setX(ptCenter.x() + (double)wRadius * (double)nFontScale * cos(dAngleE)+0.5);
                    ptPointE.setY(ptCenter.y() + (double)wRadius * (double)nFontScale * sin(dAngleE)+0.5);
                    ptCurrentPos=ptPointE;
                }

                ptCenter=CPToLP(ptCenter,nHeight,ptPointLU,dSin,dCos,dLToDScale);
                ptPointS=CPToLP(ptPointS,nHeight,ptPointLU,dSin,dCos,dLToDScale);
                ptPointE=CPToLP(ptPointE,nHeight,ptPointLU,dSin,dCos,dLToDScale);
                nRadius=(double)wRadius * (double)nFontScale / dLToDScale + 0.5;
                Arc(ptCenter.x() - nRadius,ptCenter.y() - nRadius,
                    ptCenter.x() + nRadius,ptCenter.y() + nRadius,
                    ptPointS.x(),ptPointS.y(),ptPointE.x(),ptPointE.y());

                ptPoint1=CPToLP(ptCurrentPos,nHeight,ptPointLU,dSin,dCos,dLToDScale);
                MoveTo(ptPoint1);

                wIndex1++;
            }
            bVerTextCommand=false;
            break;
        case 0xB:
            if (bVerTextCommand)  {
                wIndex1=wIndex1+6;
            }
            else  {
                wIndex1++;
                dAngleOffsetS=(double)((WORD)pbyData[wIndex1]);
                wIndex1++;
                dAngleOffsetE=(double)((WORD)pbyData[wIndex1]);
                wIndex1++;
                wRadius=(WORD)pbyData[wIndex1];
                wRadius=wRadius << 8;
                wIndex1++;
                wRadius=wRadius | (WORD)pbyData[wIndex1];
                wIndex1++;
                /*if (((char)pbyData[wIndex1]) < 0)  bClockwise=true;
                else*/  bClockwise=false;
                wArcS=(WORD)pbyData[wIndex1];
                wArcS=wArcS & 0x70;
                wArcS=wArcS >> 4;
                wSpan=(WORD)pbyData[wIndex1];
                wSpan=wSpan & 0x7;

                //计算圆心
                ptCenter=ptCurrentPos;
                ptCenter.setX(ptCenter.x() - (double)wRadius * (double)nFontScale * cos((double)wArcS * 45.0 / 180.0 * 3.14159265359)+0.5);
                ptCenter.setY(ptCenter.y() - (double)wRadius * (double)nFontScale * sin((double)wArcS * 45.0 / 180.0 * 3.14159265359)+0.5);

                dAngleS=(double)wArcS * 45.0;
                dAngleS=dAngleOffsetS * 45.0 / 256.0 + dAngleS;
                if (bClockwise)  dAngleE=-(double)wSpan * 45.0;
                else  dAngleE=(double)wSpan * 45.0;
                dAngleE=dAngleOffsetE * 45.0 / 256.0 + dAngleE;
                dAngleE=dAngleOffsetE * 45.0 / 256.0 + dAngleE;
                dAngleS=dAngleS / 180.0 * 3.14159265359;
                dAngleE=dAngleE / 180.0 * 3.14159265359;

                if (bClockwise)  {
                    ptPointS.setX(ptCenter.x() + (double)wRadius * (double)nFontScale * cos(dAngleE)+0.5);
                    ptPointS.setY(ptCenter.y() + (double)wRadius * (double)nFontScale * sin(dAngleE)+0.5);
                    ptPointE.setX(ptCenter.x() + (double)wRadius * (double)nFontScale * cos(dAngleS)+0.5);
                    ptPointE.setY(ptCenter.y() + (double)wRadius * (double)nFontScale * sin(dAngleS)+0.5);
                    ptCurrentPos=ptPointS;
                }
                else  {
                    ptPointS.setX(ptCenter.x() + (double)wRadius * (double)nFontScale * cos(dAngleS)+0.5);
                    ptPointS.setY(ptCenter.y() + (double)wRadius * (double)nFontScale * sin(dAngleS)+0.5);
                    ptPointE.setX(ptCenter.x() + (double)wRadius * (double)nFontScale * cos(dAngleE)+0.5);
                    ptPointE.setY(ptCenter.y() + (double)wRadius * (double)nFontScale * sin(dAngleE)+0.5);
                    ptCurrentPos=ptPointE;
                }

                ptCenter=CPToLP(ptCenter,nHeight,ptPointLU,dSin,dCos,dLToDScale);
                ptPointS=CPToLP(ptPointS,nHeight,ptPointLU,dSin,dCos,dLToDScale);
                ptPointE=CPToLP(ptPointE,nHeight,ptPointLU,dSin,dCos,dLToDScale);
                nRadius=(double)wRadius * (double)nFontScale / dLToDScale + 0.5;

                Arc(ptCenter.x() - nRadius,ptCenter.y() - nRadius,
                    ptCenter.x() + nRadius,ptCenter.y() + nRadius,
                    ptPointS.x(),ptPointS.y(),ptPointE.x(),ptPointE.y());

                ptPoint1=CPToLP(ptCurrentPos,nHeight,ptPointLU,dSin,dCos,dLToDScale);
                MoveTo(ptPoint1);

                wIndex1++;
            }
            bVerTextCommand=false;
            break;
        case 0xC:
            if (bVerTextCommand)  {
                wIndex1=wIndex1+4;
            }
            else  {
                wIndex1++;
                dx1=(double)((char)pbyData[wIndex1]) * (double)nFontScale;
                wIndex1++;
                dy1=(double)((char)pbyData[wIndex1]) * (double)nFontScale;
                wIndex1++;
                dBulge=(double)((char)pbyData[wIndex1]);
                /*if (((char)pbyData[wIndex1]) < 0)  bClockwise=true;
                else */ bClockwise=false;

                dD=sqrt(dx1*dx1 + dy1*dy1);
                dH=fabs(dBulge) * dD / 127.0 / 2.0;

                if (((char)pbyData[wIndex1]) == 0)  {
                    ptCurrentPos.setX(ptCurrentPos.x() + (int)dx1);
                    ptCurrentPos.setY(ptCurrentPos.y() - (int)dy1);
                    ptPoint1=CPToLP(ptCurrentPos,nHeight,ptPointLU,dSin,dCos,dLToDScale);

                    if (bPenUp)  MoveTo(ptPoint1);
                    else  LineTo(ptPoint1);
                }
                else  {
                    if (bClockwise)  {
                        dx2=-dy1;
                        dy2=dx1;
                    }
                    else  {
                        dx2=dy1;
                        dy2=-dx1;
                    }
                    dx2=dx2 / dD * dH + dx1 / 2.0;
                    dy2=dy2 / dD * dH + dy1 / 2.0;

                    CircleCR(0.0,0.0,dx2,dy2,dx1,dy1,dxc,dyc,dr);
                    ptCenter.setX(ptCurrentPos.x() + dxc + 0.5);
                    ptCenter.setY(ptCurrentPos.y() + dyc + 0.5);

                    if (bClockwise)
                    {
                        ptPointS.setX(ptCurrentPos.x() + dx1 + 0.5);
                        ptPointS.setY(ptCurrentPos.y() + dy1 + 0.5 );
                        ptPointE=ptCurrentPos;
                        ptCurrentPos=ptPointS;
                    }
                    else
                    {
                        ptPointS=ptCurrentPos;
                        ptPointE.setX(ptCurrentPos.x() + dx1 + 0.5);
                        ptPointE.setY(ptCurrentPos.y() + dy1 + 0.5);
                        ptCurrentPos=ptPointE;
                    }

                    ptCenter=CPToLP(ptCenter,nHeight,ptPointLU,dSin,dCos,dLToDScale);
                    ptPointS=CPToLP(ptPointS,nHeight,ptPointLU,dSin,dCos,dLToDScale);
                    ptPointE=CPToLP(ptPointE,nHeight,ptPointLU,dSin,dCos,dLToDScale);
                    nRadius=dr / dLToDScale + 0.5;

                    Arc(ptCenter.x() - nRadius,ptCenter.y() - nRadius,ptCenter.x() + nRadius,ptCenter.y() + nRadius,
                        ptPointS.x(),ptPointS.y(),ptPointE.x(),ptPointE.y());

                    ptPoint1=CPToLP(ptCurrentPos,nHeight,ptPointLU,dSin,dCos,dLToDScale);
                    MoveTo(ptPoint1);
                }

                wIndex1++;
            }
            bVerTextCommand=false;
            break;
        case 0xD:
            if (bVerTextCommand)  {
                wIndex1=wIndex1+4;
            }
            else  {
                wIndex1++;
                while ((pbyData[wIndex1] != 0) || (pbyData[wIndex1+1] != 0))  {
                    dx1=(double)((char)pbyData[wIndex1]) * (double)nFontScale;
                    wIndex1++;
                    dy1=(double)((char)pbyData[wIndex1]) * (double)nFontScale;
                    wIndex1++;
                    dBulge=(double)((char)pbyData[wIndex1]);
                    /*if (((char)pbyData[wIndex1]) < 0)  bClockwise=true;
                    else*/  bClockwise=false;

                    dD=sqrt(dx1*dx1 + dy1*dy1);
                    dH=fabs(dBulge) * dD / 127.0 / 2.0;

                    if (((char)pbyData[wIndex1]) == 0)  {
                        ptCurrentPos.setX(ptCurrentPos.x() + (int)dx1);
                        ptCurrentPos.setY(ptCurrentPos.y() - (int)dy1);
                        ptPoint1=CPToLP(ptCurrentPos,nHeight,ptPointLU,dSin,dCos,dLToDScale);

                        if (bPenUp)
                            MoveTo(ptPoint1);
                        else
                            LineTo(ptPoint1);
                    }
                    else  {
                        if (bClockwise)  {
                            dx2=-dy1;
                            dy2=dx1;
                        }
                        else  {
                            dx2=dy1;
                            dy2=-dx1;
                        }
                        dx2=dx2 / dD * dH + dx1 / 2.0;
                        dy2=dy2 / dD * dH + dy1 / 2.0;

                        CircleCR(0.0,0.0,dx2,dy2,dx1,dy1,dxc,dyc,dr);
                        ptCenter.setX(ptCurrentPos.x() + dxc + 0.5);
                        ptCenter.setY(ptCurrentPos.y() + dyc + 0.5);

                        if (bClockwise)
                        {
                            ptPointS.setX(ptCurrentPos.x() + dx1 + 0.5);
                            ptPointS.setY(ptCurrentPos.y() + dy1 + 0.5);
                            ptPointE=ptCurrentPos;
                            ptCurrentPos=ptPointS;
                        }
                        else
                        {
                            ptPointS=ptCurrentPos;
                            ptPointE.setX(ptCurrentPos.x() + dx1 + 0.5);
                            ptPointE.setY(ptCurrentPos.y() + dy1 + 0.5);
                            ptCurrentPos=ptPointE;
                        }

                        ptCenter=CPToLP(ptCenter,nHeight,ptPointLU,dSin,dCos,dLToDScale);
                        ptPointS=CPToLP(ptPointS,nHeight,ptPointLU,dSin,dCos,dLToDScale);
                        ptPointE=CPToLP(ptPointE,nHeight,ptPointLU,dSin,dCos,dLToDScale);
                        nRadius=dr / dLToDScale + 0.5;

                        Arc(ptCenter.x() - nRadius,ptCenter.y() - nRadius,ptCenter.x() + nRadius,ptCenter.y()  + nRadius,
                            ptPointS.x(),ptPointS.y(),ptPointE.x(),ptPointE.y());

                        ptPoint1=CPToLP(ptCurrentPos,nHeight,ptPointLU,dSin,dCos,dLToDScale);
                        MoveTo(ptPoint1);
                    }

                    wIndex1++;
                }
            }
            bVerTextCommand=false;
            break;
        case 0xE:
            bVerTextCommand=true;
            wIndex1++;
            break;
        default:
            if (bVerTextCommand)  {
                wIndex1++;
            }
            else  {
                wDirection=(WORD)(pbyData[wIndex1] % 16);
                wLength=(WORD)(pbyData[wIndex1] / 16) * (WORD)nFontScale;
                ptCurrentPos=GetNextCoodinate(wDirection,wLength,ptCurrentPos);

                ptPoint1=CPToLP(ptCurrentPos,nHeight,ptPointLU,dSin,dCos,dLToDScale);
                if (bPenUp)  MoveTo(ptPoint1);
                else  LineTo(ptPoint1);

                wIndex1++;
            }
            bVerTextCommand=false;
            break;
        }
    }
}

QPoint VectorFont::CPToLP(QPoint ptCP,int nHeight,QPoint ptPointLU,double dSin,double dCos,double dScale)
{
    double dx,dy;
    QPoint ptPoint1;

    dx=(double)ptCP.x();
    dy=(double)ptCP.y()-(double)nHeight;
    ptPoint1.setX(ptPointLU.x() + ((dx*dCos - dy*dSin) / dScale + 0.5));
    ptPoint1.setY(ptPointLU.y() + ((dx*dSin + dy*dCos) / dScale + 0.5));

    return ptPoint1;
}

//抬笔移动到点(x,y)
void VectorFont::MoveTo(long x, long y)
{
    if(x == 0){}
    if(y == 0){}
}

//抬笔移动到点ptPoint
void VectorFont::MoveTo(QPoint ptPoint)
{
    emit siMoveTo(true,ptPoint);
}

//从当前位置画线到点(x,y)
void VectorFont::LineTo(long x, long y)
{
    if(x == 0){}
    if(y == 0){}
}

//从当前位置画线到点ptPoint
void VectorFont::LineTo(QPoint ptPoint)
{
    emit siLineTo(false,ptPoint);
}

//从(x,y)点开始写字，nCount为字节数
void VectorFont::TextOutString(int x, int y, const char* lpszString, int nCount)
{
    QString strEnglish,strChinese;
    QFile fileEnglish,fileChinese;
    BYTE *pbyData;
    int nLeft;
    BYTE byByte1,byByte2;
    WORD wCharCode;
    int nIndex1,nIndex2,nIndex3,nIndex4;
    bool bEnglishChar;

    strEnglish = m_workPath + "english.fnt";
    strChinese = m_workPath + "Hz.fnt";

    fileEnglish.setFileName(strEnglish);
    if(!fileEnglish.open(QIODevice::ReadOnly))
    {
        qDebug() <<"file open failed";
        return;
    }

    fileChinese.setFileName(strChinese);
    if(!fileChinese.open(QIODevice::ReadOnly))
    {
        qDebug() <<"file open failed";
        return;
    }

    nLeft=0;
    nIndex1=0;
    while (nIndex1 < nCount)
    {
        pbyData=NULL;
        byByte1=(BYTE)lpszString[nIndex1];
        if ((byByte1 >= 128) && ((nIndex1+1) < nCount))
        {
            bEnglishChar=false;

            nIndex1++;
            byByte2=(BYTE)lpszString[nIndex1];
            wCharCode=(((WORD)byByte1) << 8) | (WORD)byByte2;

            nIndex2=0;
            nIndex3=m_nChinese_char_count - 1;
            if (m_pChinese_char[nIndex2].m_wCharCode == wCharCode)  nIndex4=nIndex2;
            else if (m_pChinese_char[nIndex3].m_wCharCode == wCharCode)  nIndex4=nIndex3;
            else nIndex4=(nIndex2 + nIndex3) / 2;
            while (((nIndex3 - nIndex2) > 1) &&
                   (m_pChinese_char[nIndex4].m_wCharCode != wCharCode))
            {
                if (m_pChinese_char[nIndex4].m_wCharCode > wCharCode)
                {
                    nIndex3=nIndex4;
                    if (nIndex2 > nIndex3) break;
                    nIndex4=(nIndex2 + nIndex3) / 2;
                }
                else
                {
                    nIndex2=nIndex4;
                    if (nIndex2 > nIndex3) break;
                    nIndex4=(nIndex2 + nIndex3) / 2;
                }
            }

            if ((m_pChinese_char[nIndex4].m_wCharCode == wCharCode) &&
                    (m_pChinese_char[nIndex4].m_wBytes > 0))
            {
                pbyData=new BYTE[m_pChinese_char[nIndex4].m_wBytes + 1];

                fileChinese.seek(m_pChinese_char[nIndex4].m_dwPosition);
                fileChinese.read((char*)pbyData,m_pChinese_char[nIndex4].m_wBytes);
            }
        }
        else
        {
            bEnglishChar=true;
            wCharCode=(WORD)byByte1;
            nIndex2=0;
            nIndex3=m_nEnglish_char_count - 1;
            if (m_pEnglish_char[nIndex2].m_wCharCode == wCharCode)  nIndex4=nIndex2;
            else if (m_pEnglish_char[nIndex3].m_wCharCode == wCharCode)  nIndex4=nIndex3;
            else nIndex4=(nIndex2 + nIndex3) / 2;
            while (((nIndex3 - nIndex2) > 1) &&
                   (m_pEnglish_char[nIndex4].m_wCharCode != wCharCode))
            {
                if (m_pEnglish_char[nIndex4].m_wCharCode > wCharCode)
                {
                    nIndex3=nIndex4;
                    if (nIndex2 > nIndex3) break;
                    nIndex4=(nIndex2 + nIndex3) / 2;
                }
                else
                {
                    nIndex2=nIndex4;
                    if (nIndex2 > nIndex3) break;
                    nIndex4=(nIndex2 + nIndex3) / 2;
                }
            }

            if ((m_pEnglish_char[nIndex4].m_wCharCode == wCharCode) &&
                    (m_pEnglish_char[nIndex4].m_wBytes > 0))  {
                pbyData=new BYTE[m_pEnglish_char[nIndex4].m_wBytes + 1];

                fileEnglish.seek(m_pEnglish_char[nIndex4].m_dwPosition);
                fileEnglish.read((char*)pbyData,m_pEnglish_char[nIndex4].m_wBytes);
            }
        }
        if (pbyData != NULL)
        {
            if (bEnglishChar)
            {
                PlotChar(QPoint(x,y),pbyData,m_pEnglish_char[nIndex4].m_wBytes,nLeft,0,m_nHeight_C);
            }
            else
            {
                PlotChar(QPoint(x,y),pbyData,m_pChinese_char[nIndex4].m_wBytes,nLeft,0,m_nInternalLeading_E + m_nHeight_E);
            }
            delete []pbyData;
            if (bEnglishChar) nLeft=nLeft + m_pEnglish_char[nIndex4].m_wWidth * m_nHeight_C;
            else nLeft=nLeft + m_nWidth_C * (m_nInternalLeading_E + m_nHeight_E);
        }
        else
        {
            if (bEnglishChar) nLeft=nLeft + m_pEnglish_char[0].m_wWidth * m_nHeight_C;
            else nLeft=nLeft + m_nWidth_C * (m_nInternalLeading_E + m_nHeight_E);
        }

        nIndex1++;
    }

    fileEnglish.close();
    fileChinese.close();
}
//画弧，从Start逆时针画到End
void VectorFont::Arc(int nLeftRect,int nTopRect,int nRightRect,int nBottomRect,
                     int nXStartArc,int nYStartArc,int nXEndArc,int nYEndArc)
{
    double dXC,dYC,dRadius;
    double dx,dy;
    double dAngleS,dAngleE,dAngle,dStep;
    double dCos,dSin;
    int nCount;

    dXC=((double)nLeftRect + (double)nRightRect) / 2.0;
    dYC=((double)nTopRect + (double)nBottomRect) / 2.0;
    dRadius=((double)nRightRect - (double)nLeftRect) / 2.0;

    dAngleS=angle_2(dXC,dYC,(double)nXStartArc,(double)nYStartArc);
    dAngleE=angle_2(dXC,dYC,(double)nXEndArc,(double)nYEndArc);
    while (dAngleE >= dAngleS) dAngleE=dAngleE - 2.0 * PI;

    if ((nXStartArc == nXEndArc) && (nYStartArc == nYEndArc))
    {
        dAngleS=0.0;
        dAngleE=-2.0 * PI;
    }

    dSin=qSin(dAngleS);
    dCos=qCos(dAngleS);
    dx=dRadius * dCos + dXC;
    dy=dRadius * dSin + dYC;
    MoveTo(dx+0.5,dy+0.5);

    nCount=120;
    dStep=PI / 180.0 * (360.0 / (double)nCount);  //3度
    dAngle=dAngleS;
    while (dAngle > dAngleE)
    {
        dAngle=dAngle - dStep;
        if (dAngle < dAngleE)  dAngle=dAngleE;
        dSin=qSin(dAngle);
        dCos=qCos(dAngle);
        dx=dRadius * dCos + dXC;
        dy=dRadius * dSin + dYC;
        LineTo(dx+0.5,dy+0.5);
    }

}

QPoint VectorFont::GetNextCoodinate(WORD wDirection,WORD wLength,QPoint ptPoint)
{
        QPoint ptPoint1;

        switch (wDirection)  {
        case 0:
                ptPoint1.setX( ptPoint.x() + (int)wLength);
                ptPoint1.setY(ptPoint.y());
                break;
        case 1:
                ptPoint1.setX(ptPoint.x() + (int)wLength);
                ptPoint1.setY(ptPoint.y() + (int)wLength/2);
                break;
        case 2:
                ptPoint1.setX(ptPoint.x() + (int)wLength);
                ptPoint1.setY(ptPoint.y() + (int)wLength);
                break;
        case 3:
                ptPoint1.setX(ptPoint.x() + (int)wLength/2);
                ptPoint1.setY(ptPoint.y() + (int)wLength);
                break;
        case 4:
                ptPoint1.setX(ptPoint.x());
                ptPoint1.setY(ptPoint.y() + (int)wLength);
                break;
        case 5:
                ptPoint1.setX(ptPoint.x() - (int)wLength/2);
                ptPoint1.setY(ptPoint.y() + (int)wLength);
                break;
        case 6:
                ptPoint1.setX(ptPoint.x() - (int)wLength);
                ptPoint1.setY(ptPoint.y() + (int)wLength);
                break;
        case 7:
                ptPoint1.setX(ptPoint.x() - (int)wLength);
                ptPoint1.setY(ptPoint.y() + (int)wLength/2);
                break;
        case 8:
                ptPoint1.setX(ptPoint.x() - (int)wLength);
                ptPoint1.setY(ptPoint.y());
                break;
        case 9:
                ptPoint1.setX(ptPoint.x() - (int)wLength);
                ptPoint1.setY(ptPoint.y() - (int)wLength/2);
                break;
        case 10:
                ptPoint1.setX(ptPoint.x() - (int)wLength);
                ptPoint1.setY(ptPoint.y() - (int)wLength);
                break;
        case 11:
                ptPoint1.setX(ptPoint.x() - (int)wLength/2);
                ptPoint1.setY(ptPoint.y() - (int)wLength);
                break;
        case 12:
                ptPoint1.setX(ptPoint.x());
                ptPoint1.setY(ptPoint.y() - (int)wLength);
                break;
        case 13:
                ptPoint1.setX(ptPoint.x() + (int)wLength/2);
                ptPoint1.setY(ptPoint.y() - (int)wLength);
                break;
        case 14:
                ptPoint1.setX(ptPoint.x() + (int)wLength);
                ptPoint1.setY(ptPoint.y() - (int)wLength);
                break;
        case 15:
                ptPoint1.setX(ptPoint.x() + (int)wLength);
                ptPoint1.setY(ptPoint.y() - (int)wLength/2);
                break;
        }

        return ptPoint1;
}

//求两点确定的直线与X轴的夹角,在[0,2pi)之间
//输入参数:
//  (startx,starty) 起点
//  (endx,endy) 终点
//返回值:
//  夹角
double VectorFont::angle_2(int startx,int starty,int endx,int endy)
{
    //直线与X轴之间的夹角 X轴向量OE(1,0)
    double dAngle = 0;
    if((endx == startx) && (endy == starty))
    {
        return dAngle;
    }
    //求直线的向量坐标
    double dX = endx - startx;
    double dY = endy - starty;
    dAngle = qAcos((dX)/(qSqrt(dX*dX + dY*dY)));
    return dAngle;
}

///////////////////////// 计算三点定圆时的圆心和半径 ///////////////////////////
// 输入参数:三个样点(x1,y1),(x2,y2),(x3,y3)
// 算法描述:
//     过(x1,y1),(x2,y2)的中点作垂线L1,
//     过(x2,y2),(x3,y3)的中点作垂线L2,
//     求L1,L2的交点.
// 输出参数:
//   如果不能形成圆返回false,
//   否则返回true其中圆心为(cx,cy),半径=cr.
//     按逆时针方向画弧时,如cr>0 则(x1,y1)是起点,(x3,y3)是终点,
//                        如cr<0 则(x3,y3)是起点,(x1,y1)是终点.
// 特别说明:此处所说的逆时针是指显示器而言,如果对于对X向右为正,
//          Y向上为正的坐标系来说此处是顺时针
//bool CircleCR(int x1,int y1,int x2,int y2,int x3,int y3,int& cx,int& cy,int& cr);
////////////////////////////////////////////////////////////////////////////////
bool VectorFont::CircleCR(double x1,double y1,double x2,double y2,double x3,double y3,double& cx,double& cy,double& cr)
{
    double a1,b1,c1,a2,b2,c2;
    if(((x1 ==x2) && (y1==y2)) || ((x1 ==x3) && (y1==y3)) || ((x2 ==x3) && (y2==y3)))
    {
        return false;
    }
    a1 = x1 - x2;
    b1 = y1 - y2;
    c1 = -a1 * (x1 + x2) / 2.0 - b1 * (y1 + y2)/2.0;
    a2 = x3 - x2;
    b2 = y3 - y2;
    c2 = -a2 * (x2 + x3) / 2.0 - b2 * (y2 + y3)/2.0;

    double D = a1*b2 - a2*b1;
    if(D == 0)//两直线平行
    {
        return false;
    }

    cx = (b1*c2 - b2*c1)/D;
    cy = (c1*a2 - c2*a1)/D;

    //用圆心和其中一个点求距离得到半径：
    cr = qSqrt((cx - x1)*(cx - x1) + (cy - y1)*(cy - y1));
    return true;
}

